import { VMFactory } from "./VMFactory";
import { CompileUtil } from "./CompileUtil";
import { Dictionary } from "../Common/Dictionary";
import { IVMComponent, ICompile, IVMMain } from "../Interfaces/IMVVM";
import VMForTransfer from "./VMForTransfer";
import CacheCommand from "./CacheCommand";

/**指令解析 */
export class Compile implements ICompile {
  vm: IVMMain;
  /**事件指令集合-方便最后再执行绑定 */
  eventCommands: Array<CacheCommand>;

  constructor(ivm) {
    this.vm = ivm;
    if (this.vm.$el) {
      this.eventCommands = new Array();
      // this.$fragment = this.nodeFragment(this.$el);
      this.compileElement(this.vm.$el);
      //绑定事件，销毁缓存命令
      while (this.eventCommands.length > 0) {
        const cmd = this.eventCommands.pop();
        CompileUtil.eventHandler(cmd.node, cmd.vm, cmd.excute, cmd.direction);
      }
      this.eventCommands = null;
      // 将文档碎片放回真实dom
      //this.$el.appendChild(this.$fragment)
    }
  }
  /**解析元素是否包含可解析参数 */
  compileElement(el, data?) {
    let self = this;
    let childNodes = VMFactory.getDirective().getChildNodes(el);

    if (childNodes) {
      [].slice.call(childNodes).forEach((node) => {
        if (self.vm.$isDestroy) {
          return;
        }
        // 如果是element节点
        if (self.isElementNode(node)) {
          self.compile(node, data);
        }
        // 解析子节点包含的指令
        var nodeChildNodes = VMFactory.getDirective().getChildNodes(node);
        if (nodeChildNodes && nodeChildNodes.length) {
          self.compileElement(node, data);
        }
      });
    }
  }
  /**节点文档缓冲处理 */
  nodeFragment(el) {
    let fragment = document.createDocumentFragment();
    let child;

    while ((child = el.firstChild)) {
      fragment.appendChild(child);
    }
    return fragment;
  }
  /**
   * 指令解析
   * @param node 解析节点
   * @param data 解析数据-for 循环时指定item数据绑定
   */
  compile(node, data?) {
    let self = this;
    var vmCompenet: IVMComponent = VMFactory.getDirective().getComponent(node);
    var vmData = data ? data : self.vm;

    if (vmCompenet) {
      var comList = this.compileIVMComponent(vmCompenet);
      for (let i = 0; i < comList.count; i++) {
        var cmdName = comList.getKey(i); //指令名称
        var cmdValue = comList.getValue(i); //指令值
        var dir = cmdName.substring(2);
        if (self.isEventDirective(dir)) {
          var cmd = new CacheCommand(node, self.vm, cmdValue, dir);
          if (self.eventCommands) {
            self.eventCommands.push(cmd);
          } else {
            CompileUtil.eventHandler(
              cmd.node,
              cmd.vm,
              cmd.excute,
              cmd.direction
            );
          }
        } else if (self.isFortDirective(dir)) {
          //如果为for 循环指令  item in data.list
          var forData = new VMForTransfer(cmdValue);
          CompileUtil[dir](node, self.vm, forData.data, forData);
        }
        // 普通指令
        else {
          if (CompileUtil[dir]) {
            CompileUtil[dir](node, self.vm, cmdValue);
          } else {
            CompileUtil.attr(node, self.vm, cmdValue, dir);
          }
        }
      }
    }
  }
  /**
   * 解析VM组件数据
   */
  compileIVMComponent(vmCompenet: IVMComponent): Dictionary<string, string> {
    var dicList = new Dictionary<string, string>();
    var VContent = "v-model=" + vmCompenet.VModel + ",";
    VContent += "v-text=" + vmCompenet.VText + ",";
    if (vmCompenet.VBind && vmCompenet.VBind.indexOf(":") < 0) {
      vmCompenet.VBind = ":click=" + vmCompenet.VBind;
    }
    VContent += "v-on" + vmCompenet.VBind + ",";
    VContent += "v-display=" + vmCompenet.VDisplay + ",";
    VContent += "v-for=" + vmCompenet.VFor + ",";
    VContent += vmCompenet.VContent == undefined ? "" : vmCompenet.VContent; //属性数组
    var contentArray = VContent.split(",");
    contentArray.forEach((attr) => {
      if (attr.indexOf("v-") === 0 && attr.indexOf("undefined") < 0) {
        var attrArray = attr.split("="); //属性分割
        if (attrArray.length == 2) {
          var attrName = attrArray[0];
          dicList.set(attrName, attrArray[1]);
        }
      }
    });
    return dicList;
  }
  // element节点
  isElementNode(node) {
    return VMFactory.getDirective().isComponent(node);
  }
  // x-XXX指令判定
  isDirective(attr) {
    return attr.indexOf("v-") === 0;
  }
  // 事件指令判定
  isEventDirective(dir) {
    return dir.indexOf("on") === 0;
  }
  // for循环指令判定
  isFortDirective(dir) {
    return dir.indexOf("for") === 0;
  }
}
